package com.xxl.job.executor.sjbank.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.executor.sjbank.mapper.*;
import com.xxl.job.executor.sjbank.pojo.*;
import com.xxl.job.executor.sjbank.service.*;
import org.apache.http.annotation.Contract;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static com.xxl.job.executor.plugin.JPubUtils.*;

/**
 * @author tsu
 * @description 针对表【con_customer(客户表)】的数据库操作Service实现
 * @createDate 2024-04-02 21:37:13
 */
@Service
public class ConCustomerServiceImpl extends ServiceImpl<ConCustomerMapper, ConCustomer>
        implements ConCustomerService {

    @Value("${inbatches}")
    private int inBatches;
    @Value("${batchsize}")
    private int batchSize;
    @Resource
    ConAddressMapper conAddressMapper;
    @Resource
    ConAddressService conAddressService;
    @Resource
    ConContactMapper conContactMapper;
    @Resource
    ConContactService conContactService;
    @Resource
    SyCustbillMapper syCustbillMapper;
    @Resource
    SyCustbillService syCustbillService;
    @Resource
    SyContactMapper syContactMapper;
    @Resource
    SyContactService syContactService;
    @Resource
    IouBillService iouBillService;
    @Resource
    IouContractService iouContractService;

    @Override
    @Transactional
    public void syncCustInfo() {
        XxlJobHelper.log("XXL-JOB, syncCustBillInfo.同步(客户合同借据联系人地址)信息开始.");

        while (true) {
            List<SyCustbill> cBList = syCustbillMapper.selectBatch(inBatches);

            XxlJobHelper.log("XXL-JOB,【每批处理数据信息数量】:{}条", cBList.size());

            if (cBList.isEmpty()) {
                XxlJobHelper.log("分批处理结束.");
                break;
            }

            // 处理当前批次客户信息
            customerOperate(cBList);

            // 处理当前批次合同信息
            contractOperate(cBList);

            // 处理当前批次借据信息
            billdataOperate(cBList);

            // 处理当前联系人和地址信息
            contAddrOperate(cBList);

            // 标记当前批次的数据为已处理
            markAsProcessed(cBList);
        }

        XxlJobHelper.log("XXL-JOB, syncCustBillInfo.同步(客户合同借据联系人地址)信息结束.");
    }

    @Transactional
    public void customerOperate(List<SyCustbill> cBList) {
        if (!cBList.isEmpty()) {
            XxlJobHelper.log("XXL-JOB, customerOpt.分批同步客户表开始.");
            List<ConCustomer> list = new ArrayList<>();
            cBList.forEach(x -> {
                ConCustomer conCustomer = new ConCustomer();
                try {
                    conCustomer.setCustomernumber(x.getCustid());
                    conCustomer.setGender(x.getGender());
                    conCustomer.setOrigin("02");
                    conCustomer.setType(1);
                    conCustomer.setCustname(x.getCustname());
                    conCustomer.setMarrgstatus(x.getMarrgstatus());
                    conCustomer.setHeightedudegr(x.getHeightedudegr());
                    conCustomer.setCorpname(x.getNameWork());
                    conCustomer.setOpenacctcerttype(x.getOpenacctcerttype());
                    conCustomer.setOpenacctcertno(x.getOpenacctcertno());
                    conCustomer.setCustphone(x.getPhone());
                    conCustomer.setProvince(x.getProvince());
                    conCustomer.setCity(x.getCity());
                    conCustomer.setDistrict(x.getDistrict());
                    conCustomer.setFlevel(x.getFivelevel());
                    conCustomer.setLastmodifiedby("system");
                    conCustomer.setLastmodifieddate(new Date());
                    conCustomer.setCreatedby("system");
                    conCustomer.setCreateddate(new Date());
                    list.add(conCustomer);

                    if (list.size() >= batchSize) {
                        saveOrUpdateBatch(list);
                        XxlJobHelper.log("Customer InsertedOrUpdate batch of size: " + list.size());
                        list.clear(); // 清空列表以准备下一批
                    }
                } catch (Exception e) {
                    XxlJobHelper.log("XXL-JOB-客户, 错误日志:" + e + ">>>>>【异常列】：" + x);
                }
            });
            if (!list.isEmpty()) {
                saveOrUpdateBatch(list);
                XxlJobHelper.log("Customer InsertedOrUpdate final batch of size: " + list.size());
            }
            XxlJobHelper.log("XXL-JOB, customerOpt.分批同步客户表结束.");
        }
    }

    private void contractOperate(List<SyCustbill> cBList) {
        if (!cBList.isEmpty()) {
            XxlJobHelper.log("XXL-JOB, ContractOperate.分批同步合同表开始.");
            List<IouContract> list = new ArrayList<>();
            cBList.forEach(x -> {
                IouContract iouContract = new IouContract();
                try {
                    iouContract.setContractnumber(x.getContractid());
                    iouContract.setContractodue(x.getContractodue());
                    iouContract.setProdcode(x.getProductnum());
                    iouContract.setCustid(x.getCustid());
                    iouContract.setLoantype(x.getLoantype());
                    iouContract.setChannelno(x.getEntrychannel());
                    iouContract.setUpdt(new Date());
                    list.add(iouContract);

                    if (list.size() >= batchSize) {
                        iouContractService.saveOrUpdateBatch(list);
                        XxlJobHelper.log("Contract InsertedOrUpdate batch of size: " + list.size());
                        list.clear(); // 清空列表以准备下一批
                    }
                } catch (Exception e) {
                    XxlJobHelper.log("XXL-JOB-合同, 错误日志:" + e + ">>>>>【异常列】：" + x);
                }
            });
            if (!list.isEmpty()) {
                iouContractService.saveOrUpdateBatch(list);
                XxlJobHelper.log("Contract InsertedOrUpdate final batch of size: " + list.size());
            }
            XxlJobHelper.log("XXL-JOB, ContractOperate.分批同步合同表结束.");
        }
    }

    private void billdataOperate(List<SyCustbill> cBList) {
        if (!cBList.isEmpty()) {
            XxlJobHelper.log("XXL-JOB, BillOperate.分批同步借据表开始.");
            List<IouBill> list = new ArrayList<>();

            cBList.forEach(x -> {
                IouBill iouBill = new IouBill();
                try {
                    iouBill.setBillid(x.getBillid());
                    iouBill.setCustomernumber(x.getCustid());
                    iouBill.setContractnumber(x.getContractid());
                    iouBill.setProductid(x.getProductnum());
                    iouBill.setChannelNo(x.getEntrychannel());
                    iouBill.setApplyAmt(StringToBigDecimal(x.getApplyprin()));
                    iouBill.setApplyDtime(StringToDate(x.getApplydt()));
                    iouBill.setApplyNumber(x.getApplyid());
                    iouBill.setLoanAmt(StringToBigDecimal(x.getLoadamt()));
                    iouBill.setLoanRate(StringToBigDecimal(x.getLoadrate()));
                    iouBill.setLoanSerialno(x.getSnum());
                    iouBill.setBeginDate(StringToDate(x.getLoadstartdt()));
                    iouBill.setSettleDate(StringToDate(x.getLoadenddt()));
                    iouBill.setRepayNum(StringToInt(x.getContractodue()));
                    iouBill.setRepayDay(StringToInt(x.getRepaydate()));
                    iouBill.setLoanBank(x.getLendingbank());
                    //iouBill.setRealSettleDate(x.);
                    iouBill.setStatus(x.getBillacctstatus());
                    iouBill.setLoanType(x.getLoantype());
                    iouBill.setLoanTypeSub(x.getLoansubtype());
                    iouBill.setCurrNum(StringToInt(x.getMthsodue()));
                    iouBill.setIsprePayment(x.getIsin());
                    iouBill.setFlevel(x.getFivelevel());
                    iouBill.setOverdueAmt(StringToBigDecimal(x.getOverdueTotal()));
                    iouBill.setOverduePrin(StringToBigDecimal(x.getOverduePrin()));
                    iouBill.setBalAmt(StringToBigDecimal(x.getLoanbalance()));
                    iouBill.setMthsOdue(x.getMthsodues());
                    iouBill.setOverdueDays(x.getMthsday());
                    iouBill.setRealRepayamt(StringToBigDecimal(x.getPaymtclrd()));
                    iouBill.setOverdueStartdt(StringToDate(x.getOverdueDt()));
                    iouBill.setOverdueInt(StringToBigDecimal(x.getOverdueInte()));
                    iouBill.setOverdueRate(StringToBigDecimal(x.getRate()));
                    iouBill.setOverdueIntp(StringToBigDecimal(x.getOverdueIntp()));
                    iouBill.setOverdueFee(StringToBigDecimal(x.getFee()));
                    iouBill.setRepayCard(x.getRepayno());
                    iouBill.setChannelNoSub(x.getEntrysubchannel());
                    iouBill.setIssumLoan(x.getIsjointloan());
                    iouBill.setFundUserName(x.getLoanparty());
                    //iouBill.setCustManager(x.);
                    iouBill.setChannelSale(x.getMarkchanneltype());
                    iouBill.setLastRepayDate(StringToDate(x.getLastrepaydt()));
                    iouBill.setLastRepayAmt(StringToBigDecimal(x.getLastrepayprin()));
                    iouBill.setMerchantId(x.getMerchant());
                    iouBill.setStores(x.getStore());
                    //iouBill.setPreFlevel(x.);
                    iouBill.setOperatorId("system");
                    iouBill.setCrdt(new Date());
                    iouBill.setUpdt(new Date());
                    list.add(iouBill);

                    if (list.size() >= batchSize) {
                        iouBillService.saveOrUpdateBatch(list);
                        XxlJobHelper.log("Bill InsertedOrUpdate batch of size: " + list.size());
                        list.clear(); // 清空列表以准备下一批
                    }
                } catch (Exception e) {
                    XxlJobHelper.log("XXL-JOB-借据, 错误日志:" + e + ">>>>>【异常列】：" + x);
                }
            });
            if (!list.isEmpty()) {
                iouBillService.saveOrUpdateBatch(list);
                XxlJobHelper.log("Bill InsertedOrUpdate final batch of size: " + list.size());
            }
            XxlJobHelper.log("XXL-JOB, BillOperate.分批同步借据表结束.");
        }
    }

    private void contAddrOperate(List<SyCustbill> cBList) {
        if (!cBList.isEmpty()) {
            XxlJobHelper.log("XXL-JOB, contAddrOperate.分批同步联系人地址表开始.");
            List<SyCustbill> dBList = new ArrayList<>(cBList.stream()
                    .collect(Collectors.toMap(
                            SyCustbill::getCustid,  // 使用 custid 作为键
                            cont -> cont,          // 值为当前对象
                            (existing, replacement) -> existing  // 如果键冲突，保留第一个
                    ))
                    .values());  // 转换回列表

            XxlJobHelper.log("XXL-JOB, contAddrOperate.去重后:{}条", dBList.size());

            List<ConContact> insertCont = new ArrayList<>();
            List<ConContact> updateCont = new ArrayList<>();
            List<ConAddress> insertAddr = new ArrayList<>();
            List<ConAddress> updateAddr = new ArrayList<>();
            dBList.forEach(x -> {
                ConContact conContact = new ConContact();
                ConAddress conAddress = new ConAddress();
                try {
                    conContact.setCustomernumber(x.getCustid());
                    conContact.setName(x.getCustname());
                    conContact.setPhone(x.getPhone());
                    conContact.setRelational("07");
                    conContact.setOrigin("3");
                    conContact.setPhntype("3");
                    conContact.setStatus(1);
                    conContact.setLastmodifiedby("system");
                    conContact.setLastmodifieddate(new Date());

                    conAddress.setCustomernumber(x.getCustid());
                    conAddress.setAddresstype("1");
                    conAddress.setOrigin("3");
                    conAddress.setProvince(x.getProvince());
                    conAddress.setCity(x.getCity());
                    conAddress.setDistrict(x.getDistrict());
                    conAddress.setAddress(x.getAddress());
                    conAddress.setLastmodifiedby("system");
                    conAddress.setLastmodifieddate(new Date());

                    ConContact ci_obj = conContactMapper.selectOne(new QueryWrapper<ConContact>().eq("customernumber", x.getCustid()).eq("phone", x.getPhone()).eq("relational", "07"));
                    ConAddress ca_obj = conAddressMapper.selectOne(new QueryWrapper<ConAddress>().eq("customernumber", x.getCustid()).eq("address", x.getAddress()));

                    if (ci_obj == null) {
                        conContact.setCreatedby("system");
                        conContact.setCreateddate(new Date());
                        insertCont.add(conContact);
                        if (insertCont.size() >= batchSize) {
                            conContactService.saveBatch(insertCont);
                            XxlJobHelper.log("Contact Inserted batch of size: " + insertCont.size());
                            insertCont.clear(); // 清空列表以准备下一批
                        }
                    } else {
                        updateCont.add(conContact);
                        if (updateCont.size() >= batchSize) {
                            XxlJobHelper.log("Contact Update batch of size: " + updateCont.size());
                            updateCont.clear(); // 清空列表以准备下一批
                        }
                        conContactService.update(null, new UpdateWrapper<ConContact>()
                                .set("name", x.getCustname())
                                .set("phone", x.getPhone())
                                .set("lastmodifiedby", "system")
                                .set("lastmodifieddate", new Date())
                                .eq("customernumber", x.getCustid())
                                .eq("phone", x.getPhone()));
                    }

                    if (ca_obj == null) {
                        conAddress.setCreatedby("system");
                        conAddress.setCreateddate(new Date());
                        insertAddr.add(conAddress);
                        if (insertAddr.size() >= batchSize) {
                            conAddressService.saveBatch(insertAddr);
                            XxlJobHelper.log("Address Inserted batch of size: " + insertAddr.size());
                            insertAddr.clear(); // 清空列表以准备下一批
                        }
                    } else {
                        updateAddr.add(conAddress);
                        if (updateAddr.size() >= batchSize) {
                            XxlJobHelper.log("Address Update batch of size: " + updateAddr.size());
                            updateAddr.clear(); // 清空列表以准备下一批
                        }
                        conAddressService.update(null, new UpdateWrapper<ConAddress>()
                                .set("addresstype", "01")
                                .set("province", x.getProvince())
                                .set("city", x.getCity())
                                .set("district", x.getDistrict())
                                .set("address", x.getAddress())
                                .set("lastmodifiedby", "system")
                                .set("lastmodifieddate", new Date())
                                .eq("customernumber", x.getCustid())
                                .eq("address", x.getAddress()));
                    }
                } catch (Exception e) {
                    XxlJobHelper.log("XXL-JOB-联系人, 错误日志:" + e + ">>>>>【异常列】：" + x);
                }
            });
            if (!insertCont.isEmpty()) {
                conContactService.saveBatch(insertCont);
                XxlJobHelper.log("Contact Inserted final batch of size: " + insertCont.size());
            }
            if (!updateCont.isEmpty()) {
                XxlJobHelper.log("Contact Update final batch of size: " + updateCont.size());
            }
            if (!insertAddr.isEmpty()) {
                conAddressService.saveBatch(insertAddr);
                XxlJobHelper.log("Address Inserted final batch of size: " + insertAddr.size());
            }
            if (!updateAddr.isEmpty()) {
                XxlJobHelper.log("Address Update final batch of size: " + updateAddr.size());
            }

            XxlJobHelper.log("XXL-JOB, contAddrOperate.分批同步联系人地址表结束.");
        }
    }

    private void markAsProcessed(List<SyCustbill> cBList) {
        if (!cBList.isEmpty()) {
            cBList.forEach(entity -> entity.setAction("1"));
            syCustbillService.updateBatchById(cBList);
            XxlJobHelper.log("XXL-JOB, markAsProcessed 标记当前批次数据{}条为已处理>>>>>", cBList.size());
        }
    }

    @Override
    public void syncContact() {
        XxlJobHelper.log("XXL-JOB, syncContact.同步(联系人)信息开始.");
        int batchSize = 50000; // 每批处理的大小

        while (true) {
            List<SyContact> cTList = syContactMapper.selectBatch(batchSize);

            XxlJobHelper.log("XXL-JOB,【每批处理数据信息数量】:{}条", cTList.size());

            if (cTList.isEmpty()) {
                XxlJobHelper.log("分批处理结束.");
                break;
            }

            // 处理当前联系人信息
            contactOperate(cTList);

            // 标记当前批次的数据为已处理
            markAsProcont(cTList);
        }

        XxlJobHelper.log("XXL-JOB, syncContact.同步(联系人)信息结束.");
    }

    private void contactOperate(List<SyContact> cTList) {
        if (!cTList.isEmpty()) {
            XxlJobHelper.log("XXL-JOB, ContactOperate.分批同步联系人表开始.");
            List<SyContact> dCList = new ArrayList<>(cTList.stream()
                    .collect(Collectors.toMap(
                            item -> item.getCustid() + "-" + item.getContactphone() + "-" + item.getContacttype(), // 组合为唯一键
                            item -> item, // 保留对象本身
                            (existing, replacement) -> existing // 如果出现重复键，保留第一个出现的对象
                    ))
                    .values());

            XxlJobHelper.log("XXL-JOB, ContactOperate.去重后:{}条", dCList.size());

            List<ConContact> insertCont = new ArrayList<>();
            List<ConContact> updateCont = new ArrayList<>();
            dCList.forEach(x -> {
                // 如果 contactphone 为空，跳过此条记录
                if (x.getContactphone() == null || x.getContactphone().isEmpty()) {
                    return;
                }

                ConContact conContact = new ConContact();
                try {
                    conContact.setCustomernumber(x.getCustid());
                    conContact.setName(x.getContactname() == null ? "空" : x.getContactname());
                    conContact.setPhone(x.getContactphone());
                    conContact.setRelational(x.getContacttype() == null ? "99" : x.getContacttype());
                    conContact.setOrigin("3");
                    conContact.setPhntype("3");
                    conContact.setStatus(1);
                    conContact.setLastmodifiedby("system");
                    conContact.setLastmodifieddate(new Date());

                    ConContact ct_obj = conContactMapper.selectOne(new QueryWrapper<ConContact>()
                            .eq("customernumber", x.getCustid())
                            .eq("phone", x.getContactphone())
                            .eq("relational", x.getContacttype() == null ? "99" : x.getContacttype()));

                    if (ct_obj == null) {
                        conContact.setCreatedby("system");
                        conContact.setCreateddate(new Date());
                        insertCont.add(conContact);
                        if (insertCont.size() >= batchSize) {
                            conContactService.saveBatch(insertCont);
                            XxlJobHelper.log("Contact Inserted batch of size: " + insertCont.size());
                            insertCont.clear(); // 清空列表以准备下一批
                        }
                    } else {
                        updateCont.add(conContact);
                        if (updateCont.size() >= batchSize) {
                            XxlJobHelper.log("Contact Update batch of size: " + updateCont.size());
                            updateCont.clear(); // 清空列表以准备下一批
                        }
                        conContactService.update(null, new UpdateWrapper<ConContact>()
                                .set("name", x.getContactname())
                                .set("phone", x.getContactphone())
                                .set("relational", x.getContacttype())
                                .set("lastmodifiedby", "system")
                                .set("lastmodifieddate", new Date())
                                .eq("customernumber", x.getCustid())
                                .eq("phone", x.getContactphone())
                                .eq("relational", x.getContacttype()));
                    }
                } catch (Exception e) {
                    XxlJobHelper.log("XXL-JOB-联系人, 错误日志:" + e + ">>>>>【异常列】：" + x);
                }
            });
            if (!insertCont.isEmpty()) {
                conContactService.saveBatch(insertCont);
                XxlJobHelper.log("Contact Inserted final batch of size: " + insertCont.size());
            }
            if (!updateCont.isEmpty()) {
                XxlJobHelper.log("Contact Update final batch of size: " + updateCont.size());
            }

            XxlJobHelper.log("XXL-JOB, ContactOperate.分批同步联系人表开始.");
        }
    }

    private void markAsProcont(List<SyContact> cTList) {
        if (!cTList.isEmpty()) {
            cTList.forEach(entity -> entity.setAction("1"));
            syContactService.updateBatchById(cTList);
            XxlJobHelper.log("XXL-JOB, markAsProcessed 标记当前批次数据{}条为已处理>>>>>", cTList.size());
        }
    }


}